package test.springboot.config;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import top.lingkang.finalsession.FinalSessionConfig;
import top.lingkang.finalsession.core.FinalRepository;
import top.lingkang.finalsession.jakarta.FinalSession;
import top.lingkang.finalsession.utils.SerializationUtils;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

/**
 * 数据库存储session
 *
 * @author lingkang
 * Created by 2024/3/10
 */
public class FinalRepositoryDatasource implements FinalRepository<FinalSession> {

    private DataSource dataSource;

    @Override
    public void initConfig(FinalSessionConfig config) {
        // 配置数据库
        HikariConfig hikariConfig = new HikariConfig();
        hikariConfig.setJdbcUrl("jdbc:mysql://localhost:3306/test?useSSL=true");
        hikariConfig.setUsername("root");
        hikariConfig.setPassword("123456");
        hikariConfig.setMaximumPoolSize(2);
        dataSource = new HikariDataSource(hikariConfig);
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            ((HikariDataSource) dataSource).close();
        }));
    }

    @Override
    public FinalSession getSession(String id) {
        Connection connection = null;
        try {
            connection = dataSource.getConnection();
            PreparedStatement statement = connection.prepareStatement("select session from fs_session where id=?");
            statement.setObject(1, id);
            ResultSet resultSet = statement.executeQuery();
            if (resultSet.next()) {
                byte[] bytes = resultSet.getBytes(1);
                resultSet.close();
                return (FinalSession) SerializationUtils.unSerialization(bytes);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            try {
                if (connection != null && !connection.isClosed())
                    connection.close();
            } catch (Exception e) {
            }
        }
        return null;
    }

    @Override
    public void setSession(String id, FinalSession session) {
        Connection connection = null;
        try {
            connection = dataSource.getConnection();
            PreparedStatement statement = connection.prepareStatement("select count(*) from fs_session where id=?");
            statement.setObject(1, id);
            ResultSet resultSet = statement.executeQuery();
            boolean exists = false;
            if (resultSet.next()) {
                if (resultSet.getLong(1) > 0)
                    exists = true;
                resultSet.close();
            }
            if (exists) {
                // 存在就更新
                statement = connection.prepareStatement("update fs_session set session=? where id=?");
                statement.setObject(1, SerializationUtils.serialization(session));
                statement.setObject(2, id);
                statement.executeUpdate();
            } else {
                // 不存在就插入
                statement = connection.prepareStatement("insert into fs_session(id,session) values(?,?) ");
                statement.setObject(1, id);
                statement.setObject(2, SerializationUtils.serialization(session));
                statement.executeUpdate();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            try {
                if (connection != null && !connection.isClosed())
                    connection.close();
            } catch (Exception e) {
            }
        }
    }

    @Override
    public void deleteSession(String id) {
        Connection connection = null;
        try {
            connection = dataSource.getConnection();
            PreparedStatement statement = connection.prepareStatement("delete from fs_session where id=?");
            statement.setObject(1, id);
            statement.executeUpdate();
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            try {
                if (connection != null && !connection.isClosed())
                    connection.close();
            } catch (Exception e) {
            }
        }
    }

    @Override
    public void destroy() {

    }
}
